using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.DebugViews;

namespace UtilZ.Dotnet.Ex.Model
{
#pragma warning disable 8500

    /// <summary>
    /// LocalSpanZ
    /// </summary>
    /// <typeparam name="T"></typeparam>
    [DebuggerTypeProxy(typeof(StructSequenceDebugView<>))]
    [DebuggerDisplay("Length = {Length}")]
    unsafe public readonly struct LocalSpanZ<T> where T : struct
    {
        /// <summary>
        /// I路指针
        /// </summary>
        public readonly T* DataPtr;

        /// <summary>
        /// 有效数据个数,最多表示到int.MaxValue个,当超出该值时,请使用LongLength
        /// </summary>
        public readonly int Length;

        /// <summary>
        /// 有效数据个数
        /// </summary>
        public readonly long LongLength;




        /// <summary>
        /// 构造函数实例化
        /// </summary>
        /// <param name="dataPtr">数据指针</param>
        /// <param name="length">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">数据长度越界异常</exception>
        /// <exception cref="NotSupportedException">数据类型不支持异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ(T* dataPtr, int length)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), "元数个数不能小于0");
            }

            this.DataPtr = dataPtr;
            this.Length = length;
            this.LongLength = length;
        }

        /// <summary>
        /// 构造函数实例化
        /// </summary>
        /// <param name="dataPtr">数据指针</param>
        /// <param name="length">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">数据长度越界异常</exception>
        /// <exception cref="NotSupportedException">数据类型不支持异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ(T* dataPtr, long length)
        {
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), "元数个数不能小于0");
            }

            this.DataPtr = dataPtr;
            if (length > int.MaxValue)
            {
                this.Length = int.MaxValue;
            }
            else
            {
                this.Length = (int)length;
            }
            this.LongLength = length;
        }

        /// <summary>
        /// 构造函数实例化
        /// </summary>
        /// <param name="data">数据</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ(in SpanZ<T> data)
        {
            this.DataPtr = data.DataPtr;
            this.Length = data.Length;
            this.LongLength = data.LongLength;
        }



        /// <summary>
        /// 判断当前数据是否为空,为空则返回值true,不为空返回false
        /// </summary>
        public bool IsEmpty
        {
#if !NET4_0
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
            get
            {
                return this.LongLength <= 0L;
            }
        }


        /// <summary>
        /// 获取或设置指定索引处的值
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public T this[long index]
        {
#if !NET4_0
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
            get
            {
                if (index < 0 || index >= this.LongLength)
                {
                    throw new IndexOutOfRangeException($"参数值无效,startIndex:{index},LongLength:{this.LongLength}");
                }

                return *(this.DataPtr + index);
            }
#if !NET4_0
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
            set
            {
                if (index < 0 || index >= this.LongLength)
                {
                    throw new IndexOutOfRangeException();
                }

                *(this.DataPtr + index) = value;
            }
        }

        /// <summary>
        /// 获取或设置指定索引处的值
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public T this[int index]
        {
#if !NET4_0
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
            get
            {
                if (index < 0 || index >= this.Length)
                {
                    throw new IndexOutOfRangeException($"参数值无效,startIndex:{index},LongLength:{this.LongLength}");
                }

                return *(this.DataPtr + index);
            }
#if !NET4_0
            [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
            set
            {
                if (index < 0 || index >= this.Length)
                {
                    throw new IndexOutOfRangeException();
                }

                *(this.DataPtr + index) = value;
            }
        }



        /// <summary>
        /// 获取第一个值,长度为0时抛出异常
        /// </summary>
        /// <returns></returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T First()
        {
            if (this.Length == 0)
            {
                throw new ArgumentException("没有数据");
            }
            else
            {
                return *this.DataPtr;
            }
        }

        /// <summary>
        /// 获取第一个值或长度为0时取类型T的默念值
        /// </summary>
        /// <returns></returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T FirstOrDefault()
        {
            if (this.Length == 0)
            {
                return default(T);
            }
            else
            {
                return *this.DataPtr;
            }
        }

        /// <summary>
        /// 获取最后一个值,长度为0时抛出异常
        /// </summary>
        /// <returns></returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T Last()
        {
            if (this.Length == 0)
            {
                throw new ArgumentException("没有数据");
            }
            else
            {
                return *(this.DataPtr + this.LongLength - 1);
            }
        }

        /// <summary>
        /// 获取最后一个值或长度为0时取类型T的默念值
        /// </summary>
        /// <returns>最后一个值或长度为0时取类型T的默念值</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T LastOrDefault()
        {
            if (this.Length == 0)
            {
                return default(T);
            }
            else
            {
                return *(this.DataPtr + this.LongLength - 1);
            }
        }



        /// <summary>
        /// 清除当前对象数据指针指向的内容
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Clear()
        {
            NativeMemory.Clear(this.DataPtr, (nuint)(sizeof(T) * this.LongLength));
        }

        /// <summary>
        /// 用指定的值填充到当前对象数据指针指向的内容
        /// </summary>
        /// <param name="value">填充值</param>        
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Fill(T value)
        {
            UnmanagedMemoryHelper.Fill(this.DataPtr, this.LongLength, value);
        }

        /// <summary>
        /// 用指定的值填充到当前对象数据指针指向的内容
        /// </summary>
        /// <param name="startIndex">起始位置</param>
        /// <param name="count">填充个数</param>
        /// <param name="value">填充值</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void Fill(long startIndex, long count, T value)
        {
            if (startIndex < 0 ||
                count < 0 ||
                startIndex + count > this.LongLength)
            {
                throw new ArgumentOutOfRangeException($"参数值无效,startIndex:{startIndex},count:{count},LongLength:{this.LongLength}");
            }

            UnmanagedMemoryHelper.Fill(this.DataPtr + startIndex, count, value);
        }





        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start'.
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ<T> Slice(int start)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},LongLength:{this.LongLength}");
            }

            return new LocalSpanZ<T>(this.DataPtr + start, this.LongLength - start);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start'.
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ<T> Slice(long start)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},LongLength:{this.LongLength}");
            }

            return new LocalSpanZ<T>(this.DataPtr + start, this.LongLength - start);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start', of given length
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <param name="length">The desired length for the slice (exclusive).</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ<T> Slice(int start, int length)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},length:{length},LongLength:{this.LongLength}");
            }

            if (start + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"start:{start},length:{length},LongLength:{this.LongLength}");
            }

            return new LocalSpanZ<T>(this.DataPtr + start, length);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start', of given length
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <param name="length">The desired length for the slice (exclusive).</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public LocalSpanZ<T> Slice(long start, long length)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start), $"start:{start},length:{length},LongLength:{this.LongLength}");
            }

            if (start + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length), $"start:{start},length:{length},LongLength:{this.LongLength}");
            }

            return new LocalSpanZ<T>(this.DataPtr + start, length);
        }

        /// <summary>
        /// Copies the contents of this span into a new array.  This heap
        /// allocates, so should generally be avoided, however it is sometimes
        /// necessary to bridge the gap with APIs written in terms of arrays.
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public T[] ToArray()
        {
            if (this.LongLength == 0)
            {
#if NET4_0
                return ArrayEx.Empty<T>();
#else
                return Array.Empty<T>();
#endif
            }

            var destination = new T[this.LongLength];
            var byteCount = this.LongLength * sizeof(T);
            fixed (T* destPtr = destination)
            {
                NativeMemory.Copy(this.DataPtr, destPtr, (nuint)(this.LongLength * sizeof(T)));
            }
            return destination;
        }

        /// <summary>
        /// 将数据拷贝到列表中
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public List<T> ToList()
        {
            if (this.LongLength == 0)
            {
                return new List<T>();
            }

            T* ptr = this.DataPtr;
            var destination = new List<T>(this.Length);
            for (int i = 0; i < destination.Count; i++)
            {
                destination.Add(*ptr++);
            }

            return destination;
        }




        ///// <summary>
        ///// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
        ///// </summary>
        //public static implicit operator LocalSpanZ<T>(T[] array)
        //{
        //    return new LocalSpanZ<T>(array);
        //}

        ///// <summary>
        ///// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
        ///// </summary>
        //public static implicit operator LocalSpanZ<T>(in Span<T> span)
        //{
        //    return new LocalSpanZ<T>(span);
        //}

        /// <summary>
        /// Defines an implicit conversion of an array to a <see cref="SpanZ{T}"/>
        /// </summary>
        public static implicit operator LocalSpanZ<T>(SpanZ<T> span)
        {
            return new LocalSpanZ<T>(span.DataPtr, span.LongLength);
        }

        /// <summary>
        /// Defines an implicit conversion of an array to a <see cref="UnmanagedMemoryPointer{T}"/>
        /// </summary>
        public static implicit operator LocalSpanZ<T>(UnmanagedMemoryPointer<T> pointer)
        {
            return new LocalSpanZ<T>(pointer.DataPtr, pointer.LongLength);
        }



        /// <summary>
        /// Returns true if left and right point at the same memory and have the same length.  Note that
        /// this does *not* check to see if the *contents* are equal.
        /// </summary>
        public static bool operator ==(LocalSpanZ<T> left, LocalSpanZ<T> right)
        {
            if (left.LongLength != right.LongLength)
            {
                return false;
            }

            if (left.DataPtr != right.DataPtr)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// Returns false if left and right point at the same memory and have the same length.  Note that
        /// this does *not* check to see if the *contents* are equal.
        /// </summary>
        public static bool operator !=(LocalSpanZ<T> left, LocalSpanZ<T> right)
        {
            return !(left == right);
        }



        /// <summary>
        /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
        /// </summary>
        /// <param name="obj">比较参数</param>
        /// <returns></returns>
        /// <exception cref="NotSupportedException">Always thrown by this method.</exception>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override bool Equals(object obj)
        {
            throw new NotSupportedException("NotSupported_CannotCallEqualsOnIQSpan");
        }

        /// <summary>
        /// This method is not supported as spans cannot be boxed.
        /// </summary>
        /// <exception cref="NotSupportedException">
        /// Always thrown by this method.
        /// </exception>
        [EditorBrowsable(EditorBrowsableState.Never)]
        public override int GetHashCode()
        {
            throw new NotSupportedException("NotSupported_CannotCallGetHashCodeOnIQSpan");
        }





        /// <summary>
        /// 转换为Span类型k
        /// </summary>
        /// <returns>Span</returns>
        /// <exception cref="ArgumentOutOfRangeException">数据长度超出Span允许的范围异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> ToSpan()
        {
            return new Span<T>(this.DataPtr, this.Length);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start'.
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> ToSpan(int start)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            return new Span<T>(this.DataPtr + start, this.Length - start);
        }

        /// <summary>
        /// Forms a slice out of the given span, beginning at 'start', of given length
        /// </summary>
        /// <param name="start">The index at which to begin this slice.</param>
        /// <param name="length">The desired length for the slice (exclusive).</param>
        /// <exception cref="ArgumentOutOfRangeException">
        /// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;Length).
        /// </exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> ToSpan(int start, int length)
        {
            if (start < 0 || start > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(start));
            }

            if (start + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new Span<T>(this.DataPtr + start, length);
        }

        /// <summary>
        /// 将当前类型强制转换为目标的类型
        /// </summary>
        /// <typeparam name="TResult">目标类型</typeparam>
        /// <returns>目标类型SpanZ</returns>
        public SpanZ<TResult> Cast<TResult>() where TResult : struct
        {
            return new SpanZ<TResult>(this.DataPtr, this.LongLength * sizeof(T) / sizeof(TResult));
        }



        /// <summary>
        /// 获取数据Span
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan()
        {
            return new Span<T>(this.DataPtr, this.Length);
        }

        /// <summary>
        /// 获取数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new Span<T>(this.DataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取数据Span
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public Span<T> GetQSpan(long startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }


            return new Span<T>(this.DataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取数据SpanZ
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetSpanZ()
        {
            return new SpanZ<T>(this.DataPtr, this.LongLength);
        }

        /// <summary>
        /// 获取数据SpanZ
        /// </summary>
        /// <param name="length">Q路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetSpanZ(int length)
        {
            if (length < 0 || length > this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.DataPtr, length);
        }

        /// <summary>
        /// 获取数据SpanZ
        /// </summary>
        /// <param name="length">Q路数据长度</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetSpanZ(long length)
        {
            if (length < 0 || length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.DataPtr, length);
        }

        /// <summary>
        /// 获取数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetSpanZ(int startIndex, int length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.DataPtr + startIndex, length);
        }

        /// <summary>
        /// 获取数据SpanZ
        /// </summary>
        /// <param name="startIndex">指针数据起始位置</param>
        /// <param name="length">获取指定长度的Span</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public SpanZ<T> GetSpanZ(long startIndex, long length)
        {
            if (startIndex < 0 || startIndex > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(startIndex));
            }

            if (length < 0 || startIndex + length > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            return new SpanZ<T>(this.DataPtr + startIndex, length);
        }






        /// <summary>
        /// 将当前数据复制到目标数据中,作参数检查
        /// </summary>
        /// <param name="destination">目标数据</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(LocalSpanZ<T> destination)
        {
            // Using "if (!TryCopyTo(...))" results in two branches: one for the length
            // check, and one for the result of TryCopyTo. Since these checks are equivalent,
            // we can optimize by performing the check once ourselves then calling Memmove directly.

            if (this.LongLength > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destination), "目标长度不足");
            }

            NativeMemory.Copy(this.DataPtr, destination.DataPtr, (nuint)(this.LongLength * sizeof(T)));
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,作参数检查
        /// </summary>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(int soucrceStartIndex, LocalSpanZ<T> destination, int destinationStartIndex, int count)
        {
            if (soucrceStartIndex < 0 || soucrceStartIndex >= this.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(soucrceStartIndex), "复制的源数据起始位置超出了当前数据容量范围");
            }

            long soucrceStartIndexL = soucrceStartIndex;
            long countL = count;
            if (soucrceStartIndexL + countL > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了当前数据容量");
            }


            long destinationStartIndexL = destinationStartIndex;
            if (destinationStartIndexL < 0 || destinationStartIndexL >= destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationStartIndex), "复制的目标数据起始位置超出了当前数据容量范围");
            }

            if (destinationStartIndex + countL > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了目标数据容量");
            }

            var byteCount = countL * sizeof(T);
            NativeMemory.Copy(this.DataPtr + soucrceStartIndex, destination.DataPtr + destinationStartIndex, (nuint)byteCount);
        }

        /// <summary>
        /// 将当前数据复制到目标数据中,作参数检查
        /// </summary>
        /// <param name="soucrceStartIndex">当前数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">复制元素个数</param>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public void CopyTo(long soucrceStartIndex, LocalSpanZ<T> destination, long destinationStartIndex, long count)
        {
            if (soucrceStartIndex < 0 || soucrceStartIndex >= this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(soucrceStartIndex), "复制的源数据起始位置超出了当前数据容量范围");
            }

            if (soucrceStartIndex + count > this.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了当前数据容量");
            }

            if (destinationStartIndex < 0 || destinationStartIndex >= destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(destinationStartIndex), "复制的目标数据起始位置超出了当前数据容量范围");
            }

            if (destinationStartIndex + count > destination.LongLength)
            {
                throw new ArgumentOutOfRangeException(nameof(count), "复制的数据长度超出了目标数据容量");
            }

            NativeMemory.Copy(this.DataPtr + soucrceStartIndex, destination.DataPtr + destinationStartIndex, (nuint)(count * sizeof(T)));
        }






        /// <summary>
        /// 从source拷贝count个元素数据到destination
        /// </summary>
        /// <param name="source">源数据</param>
        /// <param name="destination">目标数据</param>
        /// <exception cref="ArgumentOutOfRangeException">个数超出索引异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(LocalSpanZ<T> source, LocalSpanZ<T> destination)
        {
            NativeMemory.Copy(source.DataPtr, destination.DataPtr, (nuint)(source.LongLength * sizeof(T)));
        }

        /// <summary>
        /// 从source拷贝count个元素数据到destination
        /// </summary>
        /// <param name="source">源数据</param>
        /// <param name="soucrceStartIndex">源数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">个数超出索引异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(LocalSpanZ<T> source, int soucrceStartIndex, LocalSpanZ<T> destination, int destinationStartIndex, int count)
        {
            NativeMemory.Copy(source.DataPtr + soucrceStartIndex, destination.DataPtr + destinationStartIndex, (nuint)(count * sizeof(T)));
        }

        /// <summary>
        /// 从source拷贝count个元素数据到destination
        /// </summary>
        /// <param name="source">源数据</param>
        /// <param name="soucrceStartIndex">源数据起始位置</param>
        /// <param name="destination">目标数据</param>
        /// <param name="destinationStartIndex">目标数据起始位置</param>
        /// <param name="count">元素个数</param>
        /// <exception cref="ArgumentOutOfRangeException">个数超出索引异常</exception>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public static void Copy(LocalSpanZ<T> source, long soucrceStartIndex, LocalSpanZ<T> destination, long destinationStartIndex, long count)
        {
            NativeMemory.Copy(source.DataPtr + soucrceStartIndex, destination.DataPtr + destinationStartIndex, (nuint)(count * sizeof(T)));
        }






        /// <summary>
        /// Copies the contents of this span into destination span. If the source
        /// and destinations overlap, this method behaves as if the original values in
        /// a temporary location before the destination is overwritten.
        /// </summary>
        /// <param name="destination">The span to copy items into.</param>
        /// <returns>If the destination span is shorter than the source span, this method
        /// return false and no data is written to the destination.</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public bool TryCopyTo(SpanZ<T> destination)
        {
            if (this.LongLength > destination.LongLength)
            {
                return false;
            }

            NativeMemory.Copy(this.DataPtr, destination.DataPtr, (nuint)(this.LongLength * sizeof(T)));
            return true;
        }


        /// <summary>
        /// Copies the contents of this span into destination span. If the source
        /// and destinations overlap, this method behaves as if the original values in
        /// a temporary location before the destination is overwritten.
        /// </summary>
        /// <param name="destination">The span to copy items into.</param>
        /// <returns>If the destination span is shorter than the source span, this method
        /// return false and no data is written to the destination.</returns>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        public bool TryCopyTo(LocalSpanZ<T> destination)
        {
            if (this.LongLength > destination.LongLength)
            {
                return false;
            }

            NativeMemory.Copy(this.DataPtr, destination.DataPtr, (nuint)(this.LongLength * sizeof(T)));
            return true;
        }






        /// <summary>
        /// 获取枚举器
        /// </summary>
        /// <returns>枚举器</returns>
        public IEnumerator GetEnumerator()
        {
            return new PointerEnumerator<T>(this.DataPtr, this.LongLength);
        }

        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>String</returns>
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            T* ptr = this.DataPtr;
            for (long i = 0; i < this.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.AppendLine();
                }

                sb.Append((*ptr).ToString());
                ptr++;
            }

            return sb.ToString();
        }

        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>String</returns>
        public string ToString(char separator)
        {
            StringBuilder sb = new StringBuilder();
            T* ptr = this.DataPtr;
            for (long i = 0; i < this.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append((*ptr).ToString());
                ptr++;
            }

            return sb.ToString();
        }

        /// <summary>
        /// 重写ToString
        /// </summary>
        /// <returns>String</returns>
        public string ToString(string separator)
        {
            StringBuilder sb = new StringBuilder();
            T* ptr = this.DataPtr;
            for (long i = 0; i < this.LongLength; i++)
            {
                if (sb.Length > 0)
                {
                    sb.Append(separator);
                }

                sb.Append((*ptr).ToString());
                ptr++;
            }

            return sb.ToString();
        }

    }


}
